package com.exsun.gateway.jt809.codec;

import com.exsun.gateway.jt809.common.LinkType;
import com.exsun.gateway.jt809.config.NettyClientConfig;
import com.exsun.gateway.jt809.data.MsgHeader;
import com.exsun.gateway.jt809.data.PackageData;
import com.exsun.gateway.jt809.master.handler.JT809ClientInitializer;
import com.exsun.gateway.jt809.slave.handler.JT809ServerChannelInitializer;
import exsun.jt808.data.util.SAContextHolder;
import exsun.jt808.data.util.parse.BitOperator;
import exsun.jt808.data.util.parse.CRC16;
import exsun.jt808.data.util.parse.DecoderUtils;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;


import java.util.List;
@Component
public class MsgDecoder extends ByteToMessageDecoder {

	private static final Logger logger = Logger.getLogger(MsgDecoder.class);

	NettyClientConfig nettyClientConfig;

	private LinkType linkType;

	public MsgDecoder(){
	}

	public MsgDecoder(JT809ServerChannelInitializer jt809ServerChannelInitializer){
		this.nettyClientConfig = jt809ServerChannelInitializer.nettyClientConfig;
		this.linkType = jt809ServerChannelInitializer.LINK_TYPE;
	}

	public MsgDecoder(JT809ClientInitializer jt809ClientInitializer) {
		this.nettyClientConfig = jt809ClientInitializer.nettyClientConfig;
		this.linkType = jt809ClientInitializer.LINK_TYPE;
	}

	@Override
	protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List<Object> out)
			throws Exception {
		if (buf.readableBytes() <= 0) {
			return;
		}
		logger.info("rec:"+ByteBufUtil.hexDump(buf));

		byte[] bs = new byte[buf.readableBytes()];
		buf.readBytes(bs);
		PackageData pkd = bytes2PackageData(bs);
		if (pkd == null || (!pkd.isValid())) {
			return;
		}
		pkd.setLinkType(linkType);
		out.add(pkd);
	}

	private PackageData bytes2PackageData(byte[] rec) throws Exception {
		byte[] data = JT809ProtocolUtils.doEscape4Receive(rec);
		PackageData ret = new PackageData();
		byte[] headAndbody = DecoderUtils.byteCopy(data, 0, data.length - 2);
		byte[] crc = DecoderUtils.byteCopy(data, data.length - 2, 2);
		int crc_code = BitOperator.byteToInteger(crc);
		if (CRC16.getCRC(headAndbody) != crc_code) {
			return ret;
		}
		ret.setValid(true);
		MsgHeader msgHeader = parseMsgHeaderFromBytes(data);
		byte[] msgBodyBytes = DecoderUtils.byteCopy(headAndbody, 22, headAndbody.length - 22);
		if (msgHeader.getEncryptFlag() == 1) {
			JT809ProtocolUtils.accMsgEncrypt(msgHeader.getEncryptKey(), msgBodyBytes,
					nettyClientConfig.getIA1(),
					nettyClientConfig.getM1(),
					nettyClientConfig.getIC1());
		}
		logger.info(ByteBufUtil.hexDump(msgBodyBytes));
		ret.setMsgBodyBytes(msgBodyBytes);
		ret.setMsgHeader(msgHeader);
		return ret;
	}

	private MsgHeader parseMsgHeaderFromBytes(byte[] data) {
		MsgHeader msgHeader = new MsgHeader();
		// 1. 22byte 消息头 (4 + 4 + 2 + 4 + 3 + 1 + 4)
		byte[] header = DecoderUtils.byteCopy(data, 0, 22);
		// 消息流水号
		msgHeader.setFlowId(DecoderUtils.parseIntFromBytes(header, 4, 4));
		// 消息ID
		msgHeader.setMsgId(DecoderUtils.parseIntFromBytes(header, 8, 2));
		// 接入码
		msgHeader.setCenterid(DecoderUtils.fourBytesToLong(header, 10));
		// 是否加密
		msgHeader.setEncryptFlag(DecoderUtils.parseIntFromBytes(header, 17, 1));
		// 加密key
		msgHeader.setEncryptKey(DecoderUtils.parseIntFromBytes(header, 18, 4));
		return msgHeader;
	}

}
